package com.xxxx.microservice.forestry.service;

import com.alibaba.fastjson.JSONObject;
import com.xxxx.microservice.forestry.component.SuperMapCom;
import com.xxxx.microservice.forestry.dto.data.Dic;
import com.xxxx.microservice.forestry.dto.param.FeatureAnalysisParam;
import com.xxxx.microservice.forestry.dto.param.InterpolateParam;
import com.xxxx.microservice.forestry.dto.param.QueryCommonParam;
import com.xxxx.microservice.forestry.dto.param.QueryParam;
import com.xxxx.microservice.forestry.dto.result.*;
import com.xxxx.microservice.forestry.enums.InterpolateQuota;
import com.xxxx.microservice.forestry.mapper.ExampleMapper;
import com.xxxx.microservice.forestry.mapper.ForestryMapper;
import com.xxxx.microservice.forestry.utils.EquiSurface;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.geojson.feature.FeatureJSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class ForestryService {

    private static final Logger LOGGER = LoggerFactory.getLogger(ForestryService.class);

    @Autowired
    private SuperMapCom superMapCom;

    @Autowired
    private ForestryMapper forestryMapper;

    @Autowired
    private ExampleMapper exampleMapper;

    public List<Dic> getXzqTree() {
        return forestryMapper.getXzqTree();
    }

    public String getXzqRange(String xzqdm) {
        String tableName = "xzq_xiang";
        String pac = xzqdm;
        if (xzqdm.length() == 2) {
            tableName = "xzq_shi";
            pac = xzqdm + "0000000";
        } else if (xzqdm.length() == 6) {
            tableName = "xzq_qu";
            pac = xzqdm + "000";
        }
        return forestryMapper.getXzqRange(tableName, pac);
    }

    public List<SamplingPoint> queryAllPoint() {
        return forestryMapper.selectAllPoint();
    }

    public List<Map<String, Object>> queryTable(String xzqdm, String ydbh, String table, String filed) {
        return forestryMapper.selectTable(xzqdm, ydbh, table, filed);
    }

    public List<Map<String, Object>> queryPjjg(String xzqdm, String ydbh, String table) {
        return forestryMapper.queryPjjg(xzqdm, ydbh, table);
    }

    public Map<String, Object> iQuery(String ydbh) {
//        return forestryMapper.iQuery(ydbh);
        QueryCommonParam queryCommonParam = new QueryCommonParam();
        queryCommonParam.setYdbh(ydbh);
        List<Map<String, Object>> res = forestryMapper.queryCommon(queryCommonParam);
        if (!res.isEmpty()) {
            return res.get(0);
        } else {
            return new HashMap<>();
        }
    }

    public List<Map<String, Object>> query(QueryCommonParam queryCommonParam) {
        return forestryMapper.queryCommon(queryCommonParam);
    }

    public String interpolate(InterpolateParam interpolateParam) throws Exception {
        try {
            String xzqdm = interpolateParam.getXzqdm();
            if (xzqdm == null || "".equals(xzqdm)) {
                xzqdm = "11";
            }
            String quyujson = getXzqRange(xzqdm);
            JSONObject jsonObject = JSONObject.parseObject(quyujson);
            jsonObject.remove("crs");
            quyujson = jsonObject.toJSONString();
            quyujson = "{\"type\": \"FeatureCollection\", \"features\": [{\"type\": \"Feature\", \"geometry\": " + quyujson + "}]}";
            FeatureJSON fJson = new FeatureJSON();
            SimpleFeatureCollection featureCollection = (SimpleFeatureCollection) fJson.readFeatureCollection(quyujson);

            if (interpolateParam.getQuota() == InterpolateQuota.ph) {
                List<Map<String, Object>> res = exampleMapper.ph(interpolateParam.getXzqdm());
                double[][] trainData = new double[res.size()][3];
                for (int i = 0; i < res.size(); i++){
                    trainData[i][0] = (Double) res.get(i).get("cyjd");
                    trainData[i][1] = (Double) res.get(i).get("cywd");
                    trainData[i][2] = (Double) res.get(i).get("ph");
                }
                double[] dataInterval = new double[]{4.5,5.5,6.5,7.5,8.5};
                int[] size = new int[]{100, 100};
                String strJson = EquiSurface.calEquiSurface(trainData, dataInterval, size, featureCollection, true);
                return strJson;
            } else {
                List<Map<String, Object>> res = exampleMapper.om(interpolateParam.getXzqdm());
                double[][] trainData = new double[res.size()][3];
                for (int i = 0; i < res.size(); i++){
                    trainData[i][0] = (Double) res.get(i).get("cyjd");
                    trainData[i][1] = (Double) res.get(i).get("cywd");
                    trainData[i][2] = (Double) res.get(i).get("om");
                }
                double[] dataInterval = new double[]{6,10,20,30,40};
                int[] size = new int[]{100, 100};
                String strJson = EquiSurface.calEquiSurface(trainData, dataInterval, size, featureCollection, true);
                return strJson;
            }
        } catch (Exception e) {
            throw e;
        }
    }

    public int insertPoints(List<Map<String, Object>> pointList) {
        try {
            return forestryMapper.insertPoints(pointList);
        } catch (Exception e) {
            // 打印错误
            LOGGER.error(e.toString());
            throw e;
        }
    }


    public int pointsTemp(List<Map<String, Object>> pointList) {
        try {
            return forestryMapper.pointsTemp(pointList);
        } catch (Exception e) {
            // 打印错误
            LOGGER.error(e.toString());
            throw e;
        }
    }

    public List<FeatureAnalysisResult> featureAnalysis(FeatureAnalysisParam featureAnalysisParam) {
        String xzqdm = featureAnalysisParam.getXzqdm();
        List<String> quotas = Arrays.asList(featureAnalysisParam.getQuotas().split(","));
        List<List<Double>> valueList = new ArrayList<>();
        for (String ignored : quotas) {
            valueList.add(new ArrayList<>());
        }
        List<Map<String, Object>> data = forestryMapper.quotaValue(xzqdm, quotas);
        for (int i = 0; i < quotas.size(); i++) {
            List<Double> curList = valueList.get(i);
            for (Map<String, Object> re : data) {
                String vv = re.get(quotas.get(i)).toString();
                curList.add(Double.valueOf(vv));
            }
        }

        List<FeatureAnalysisResult> featureAnalysisResults = new ArrayList<>();
        for (int i = 0; i < quotas.size(); i++) {
            FeatureAnalysisResult featureAnalysisResult = compute(valueList.get(i));
            featureAnalysisResult.setQuota(quotas.get(i));
            featureAnalysisResults.add(featureAnalysisResult);
        }

        return featureAnalysisResults;
    }

    public FeatureAnalysisResult compute(List<Double> values) {
        FeatureAnalysisResult far = new FeatureAnalysisResult();
        if (values.isEmpty()) {
            return far;
        }

        // 排序
        values.sort(Comparator.comparingDouble(Double::valueOf));

        // 最大值
        far.setMax(values.get(values.size() - 1));
        // 最小值
        far.setMin(values.get(0));

        // 合计值
        double total = 0.0;
        for (Double value : values) {
            total += value;
        }

        // 均值
        double avg = total / values.size();
        far.setAvg(avg);

        // 中位数
        if (values.size() % 2 == 0) {
            int i = values.size() / 2;
            far.setFenweishu((values.get(i - 1) + values.get(i)) / 2);
        } else {
            far.setFenweishu(values.get(values.size() / 2));
        }

        // 方差
        double fangcha = 0.0;
        for (Double value : values) {
            fangcha += Math.pow((value - avg), 2);
        }
        fangcha = fangcha / values.size();
        far.setFangcha(fangcha);

        // 标准差
        double biaozhuncha = Math.sqrt(fangcha);

        // 偏度
        double piandu = 0.0;
        // 峰度
        double fengdu = 0.0;
        for (Double value : values) {
            piandu += Math.pow((value - avg) / biaozhuncha, 3);
            fengdu += Math.pow((value - avg) / biaozhuncha, 4);
        }
        piandu = piandu / values.size();
        fengdu = fengdu / values.size();

        far.setPiandu(piandu);
        far.setFengdu(fengdu);

        return far;
    }

    public List<ClusterResult> clusterOutlierAnalyst(String xzqdm, String field) {
        String sql = null;
        if (xzqdm != null && !xzqdm.isEmpty()) {
            sql = "ZLDWDM like '" + xzqdm + "%'";
        }
        return superMapCom.clusterOutlierAnalyst(sql, field);
    }

    public AutoCorrelationResult autoCorrelation(String xzqdm, String field) {
        String sql = null;
        if (xzqdm != null && !xzqdm.isEmpty()) {
            sql = "ZLDWDM like '" + xzqdm + "%'";
        }
        return superMapCom.autoCorrelation(sql, field);
    }
    
    public List<QueryResult> spatialQuery(String datasetname, String fieldtype) {
    	if(datasetname.equals("1") || datasetname.equals("土地利用")) {
    		String targetDatasetName = "地类图斑";
    		String queryAttribute = "Substr(DLBM, 0,3)='" + fieldtype + "'";
    		return superMapCom.spatialQuery(targetDatasetName, queryAttribute);
    	}
    	if(datasetname.equals("2") || datasetname.equals("林地小班")) {
    		String targetDatasetName = "pgxb";
    		String queryAttribute = "OBJECTID<1"; //随便设个条件，当参数不正确时查询为空
    		if(fieldtype.equals("03")) {
    			queryAttribute = "一级地='林地'";
    		} else if(fieldtype.equals("05")) {
    			queryAttribute = "一级地='非林地'";
    		}	
    		return superMapCom.spatialQuery(targetDatasetName, queryAttribute);
    	}
        return new ArrayList<>();
    }

    public List<Map<String, Object>> polygonAnalysis (String where, String type, String value, String groupBy) {
        return forestryMapper.polygonAnalysis(where, type, value, groupBy);
    }

    public List<Map<String, Object>> pointStatic (String xzqdm, String quotas) {
        return forestryMapper.pointStatic(xzqdm, quotas);
    }

    public List<Map<String, Object>> ldxbAssess (String xzqdm, String quotas) {
        return forestryMapper.ldxbAssess(xzqdm, quotas);
    }

    public  List<Map<String, Object>> dltbAssess (String xzqdm, String quotas) {
        return forestryMapper.dltbAssess(xzqdm, quotas);
    }
}
